package nessie;

/**
 * this class handles the CPU flag operations. and while most operations are pretty
 * straightforward, some special cases exist.
 */
public class Flags {

    private Flags() {
    }
    /**Break Command*/
    public static boolean B;
    /**Carry Flag*/
    public static byte C;
    /**Decimal Mode Flag*/
    public static boolean D;
    /**Interrupt Disable*/
    public static boolean I;
    /**Negative Flag*/
    public static boolean N;
    /**Overflow Flag*/
    public static boolean V;
    /**Zero Flag*/
    public static boolean Z;

    public static void setZeroFlag(short register) {
        if (register == 0) {
            Z = true;//Z= (register == 0);
        } else {
            Z = false;
        }
    }
    private static final int NEGATIVE = 0b1000_0000;

    public static void setNegativeFlag(short register) {
        if ((register & NEGATIVE) == NEGATIVE) {
            N = true;
        } else {
            N = false;
        }
    }

    /**
     * <editor-fold defaultstate="collapsed" desc="http://nesdev.parodius.com/bbs/viewtopic.php?t=6331">
     ********/
    /**
     * signed overflow
     *
     * this function compares the AND of the signs of the first AND second operands to the sign of the result
     * e.g.(8bits)
     *       A=64, B=64, result=-1
     * signs:A=+,  B=+,  result=-
     * cmp  :+ AND + = +, is + == result sign -> is + == -, if not, then overflow has occured
     * @param A first operand
     * @param B second operand
     * @param result the sum of the first and second operands
     * @return the first operand
     */
    public static byte setOverflowFlag(byte A, byte B, byte result) {
        if (((A & 0x80) != (result & 0x80))
                && ((B & 0x80) != (result & 0x80))) {
            V = true;
        } else {
            V = false;
        }
        return (byte) A;
    }
    private static final int Unsigned_Byte_MAX_VALUE = 0xFF;

    /**unsigned overflow for ADC*/
    public static void setCarryFlag(short register) {
        if (register < 0 || register > Unsigned_Byte_MAX_VALUE) {
            Flags.C = 0x1;
        } else {
            Flags.C = 0b0;
        }
    }

    /**unsigned overflow for SBC*/
    public static void setNotCarryFlag(short register) {
        setCarryFlag(register);
        Flags.C = (byte) (Flags.C == 1 ? 0 : 1);
    }

    /**this function does not check for overflows, it only checks whether the result of CMP, CPX or CPY result is <b>larger than or equal</b> to <b>0</b>.*/
    public static void setCarryFlagForCMP(short register) {
        if (register >= 000) {
            Flags.C = 0x1;
        } else {
            Flags.C = 0b0;
        }
    }
    /********
     *</editor-fold>
     */
}
